<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of BDbAdapter
 *
 * @author jianfeng
 */
class BDbAdapter {

    private $app = null;

    public function __construct($app = null) {
        if ($app != null)
            $this->app = $app;
    }

    public function getOperationById($operationId) {
        $result = array();

        $sql = "select * from bln_application_operation where _id = :OperationId";

        $db = Yii::app()->getDb();

        $command = $db->createCommand($sql);

        $command->bindParam(":OperationId", $operationId, PDO::PARAM_INT);

        $dataReader = $command->query();

        foreach ($dataReader as $row) {
            $result['AppId'] = $row['app_id'];
            $result['OperationName'] = $row['operationname'];
            $result['FunctionName'] = $row['functionname'];
            $result['Description'] = $row['description'];
            $result['OperationData'] = unserialize($row['operationdata']);
        }

        return $result;
    }

    public function getRoleId($appId, $roleName) {

        $sql = "select _id from bln_application_authitem where app_id = :appId 
                and authname = :authName";

        $mRole = BMApplicationAuthItem::model()->findBySql($sql, array(':appId' => $appId,
            'authName' => $roleName));

        if ($mRole == null)
            return -1;
        else
            return $mRole->_id;
    }

    public function addServiceApp($serviceId, $appId) {
        //add serviceapp to new service
        $newService_serviceApp = new BMServiceApplication();
        $newService_serviceApp->app_id = $appId;
        $newService_serviceApp->service_id = $serviceId;

        return $newService_serviceApp->save();
    }

    public function getServiceAppClass($appId) {

        $sql = "select classname from bln_application where _id = :AppId";

        $db = Yii::app()->getDb();

        $command = $db->createCommand($sql);

        $command->bindParam(":AppId", $appId, PDO::PARAM_INT);

        $appClass = $command->queryScalar();

        return $appClass;
    }

    public function getServiceAppId($classname) {

        $app = null;

        $sql = "select * from bln_application where classname = :ClassName";

        $app = BMServiceApplication::model()->findBySql($sql, array(":ClassName" => $classname));

        if ($app == null)
            return FALSE;
        else {
            $id = $app->_id;
            return $id;
        }
    }

    public function registerServiceApp($meta) {
        $appshowable = true;
        $description = NULL;

        $appname = isset($meta['appName']) ? $meta['appName'] : $meta['appname'];
        $appclass = isset($meta['appClass']) ? $meta['appClass'] : $meta['appclass'];

        if (isset($meta['showAble']))
            $appshowable = $meta['showAble'];

        if (isset($meta['description']))
            $description = $meta['description'];

        $selectSql = "select * from bln_application where classname = :ClassName";

        $updateSql = "update bln_application set appname = :AppName,showable = :Showable,
            description = :Description where classname = :ClassName";

        $sql = "insert bln_application(appname,classname,showable,description)values(
            :AppName,:ClassName,:Showable,:Description)";

        $db = Yii::app()->getDb();

        $selectCmd = $db->createCommand($selectSql);
        $selectCmd->bindParam(":ClassName", $appclass, PDO::PARAM_STR);

        $appId = $selectCmd->queryScalar();

        if ($appId == NULL) {
            $insertCmd = $db->createCommand($sql);
            $insertCmd->bindParam(":AppName", $appname, PDO::PARAM_STR);
            $insertCmd->bindParam(":ClassName", $appclass, PDO::PARAM_STR);
            $insertCmd->bindParam(":Showable", $appshowable, PDO::PARAM_BOOL);
            $insertCmd->bindParam(":Description", $description, PDO::PARAM_STR);
            $insertCmd->execute();
        } else {
            $updateCmd = $db->createCommand($updateSql);
            $updateCmd->bindParam(":AppName", $appname, PDO::PARAM_STR);
            $updateCmd->bindParam(":Showable", $appshowable, PDO::PARAM_BOOL);
            $updateCmd->bindParam(":Description", $description, PDO::PARAM_STR);
            $updateCmd->bindParam(":ClassName", $appclass, PDO::PARAM_STR);
            $updateCmd->execute();
        }

        $appId = $this->getServiceAppId($appclass);

        if (isset($meta['visible'])) {

            $config = $meta['visible'];

            $config['appId'] = $appId;

            $this->registerVisibility($config, $db);
        }
        return $appId;
    }

    public function getServiceScopeTypeId($scopename) {
        $sql = "select _id from bln_service_scopetype where scopename = :ScopeName";

        $db = Yii::app()->getDb();

        $command = $db->createCommand($sql);

        $command->bindParam(":ScopeName", $scopename, PDO::PARAM_STR);

        return $command->queryScalar();
    }

    public function registerVisibility($config, $conn = null) {

        $selectSql = "select * from bln_service_application_visible 
            where app_id = :AppId and service_scopetype_id = :ScopeTypeId and service_scope_id = :ScopeId";

        $updateSql = "update bln_service_application_visible set apply_rule = :ApplyRule 
            where app_id = :AppId and service_scopetype_id = :ScopeTypeId and service_scope_id = :ScopeId";

        $sql = "insert bln_service_application_visible(app_id,service_scopetype_id,service_scope_id,apply_rule)
            values(:AppId,:ScopeTypeId,:ScopeId,:ApplyRule)";

        //by default, applyRule = 'exclude'
        $applyRule = 'exclude';

        $appId = $config['appId'];
        $scopeTypeId = $this->getServiceScopeTypeId($config['scopeType']);
        $scopeId = $this->getScopeId($config['scopeType'], $config['scope']);
        $applyRule = $config['applyRule'];

        if ($conn == null)
            $db = Yii::app()->getDb();
        else
            $db = $conn;

        $selectComm = $db->createCommand($selectSql);

        $selectComm->bindParam(":AppId", $appId, PDO::PARAM_INT);
        $selectComm->bindParam(":ScopeTypeId", $scopeTypeId, PDO::PARAM_INT);
        $selectComm->bindParam(":ScopeId", $scopeId, PDO::PARAM_INT);

        $retId = $selectComm->queryScalar();

        if ($retId != NULL) {
            $updateComm = $db->createCommand($updateSql);

            $updateComm->bindParam(":AppId", $appId, PDO::PARAM_INT);
            $updateComm->bindParam(":ScopeTypeId", $scopeTypeId, PDO::PARAM_INT);
            $updateComm->bindParam(":ScopeId", $scopeId, PDO::PARAM_INT);
            $updateComm->bindParam(":ApplyRule", $applyRule, PDO::PARAM_STR);

            return $updateComm->execute();
        } else {

            $command = $db->createCommand($sql);

            $command->bindParam(":AppId", $appId, PDO::PARAM_INT);
            $command->bindParam(":ScopeTypeId", $scopeTypeId, PDO::PARAM_INT);
            $command->bindParam(":ScopeId", $scopeId, PDO::PARAM_INT);
            $command->bindParam(":ApplyRule", $applyRule, PDO::PARAM_STR);

            return $command->execute();
        }

        return FALSE;
    }

    public function getScopeId($scopeType, $scope) {

        if ($scopeType == BServiceApp::SERVICESCOPETYPE) {
            return $scope;
        }

        if ($scopeType == BServiceApp::SERVICETYPESCOPETYPE) {
            return $this->getServiceTypeId($scope);
        }
    }

    public function getServiceTypeId($typeName) {
        return BMServiceType::model()->find("typename=:typeName", array(":typeName" => $typeName))->_id;
    }

    public function getServiceCategoryId($categoryName) {
        return BMServiceCategory::model()->find("categoryname=:cateName", array(":cateName" => $categoryName))->_id;
    }

    public function getServiceCategorys($serviceId) {
        $sql = "select sc.servicecategory_id as category_id from bln_servicecategory c, bln_service_servicecategory sc 
            where sc.service_id = :ServiceId and sc.servicecategory_id = c._id";

        $db = Yii::app()->getDb();

        $command = $db->createCommand($sql);

        $command->bindParam(":ServiceId", $serviceId, PDO::PARAM_INT);

        $dataReader = $command->query();

        $mCategorys = array();

        foreach ($dataReader as $row) {
            array_push($mCategorys, BMServiceCategory::model()->findByPk($row['category_id']));
        }

        return $mCategorys;
    }

    public function isVisible($serviceId = null, $serviceTypeId = null, $serviceCategoryIds = null) {

        $sql = "select t.scopename,service_scope_id,apply_rule 
            from bln_service_application_visible v, bln_service_scopetype t  
                    where v.service_scopetype_id = t._id and 
                    app_id = :AppId and 
                    v.apply_rule = :ApplyRule";

        $db = Yii::app()->getDb();

        $command = $db->createCommand($sql);

        $appId = $this->app->getId();
        $applyRule = BServiceApp::INCLUDEAPPLYRULE;

        $command->bindParam(":AppId", $appId, PDO::PARAM_INT);
        $command->bindParam(":ApplyRule", $applyRule, PDO::PARAM_STR);

        //first get all value of current app in visible table
        $include_rows = $command->query();
        $include_count = $include_rows->count();

        //if have include setting, other in list will be invisible
        //include will work first before exclude
        if ($include_rows != null && $include_count > 0) {
            foreach ($include_rows as $row) {
                if ($row['scopename'] == BServiceApp::SERVICETYPESCOPETYPE) {
                    if ($serviceTypeId == $row['service_scope_id']) {
                        return TRUE;
                    }
                }

                if ($row['scopename'] == BServiceApp::SERVICESCOPETYPE) {
                    if ($serviceId == $row['service_scope_id'])
                        return TRUE;
                }

                if ($row['scopename'] == BServiceApp::SERVICECATEGORYSCOPETYPE) {
                    foreach ($serviceCategoryIds as $serviceCategoryId) {
                        if ($serviceCategoryId == $row['service_scope_id'])
                            return TRUE;
                    }
                }
            }
            return FALSE;
        }

        $excludeRule = BServiceApp::EXCLUDEAPPLYRULE;

        $command->bindParam(":ApplyRule", $excludeRule, PDO::PARAM_STR);

        $exclude_rows = $command->query();

        $exclude_count = $exclude_rows->count();

        //if exist exclude list, other will be visible
        //if have include, exclude do not work
        if ($exclude_rows != null && $exclude_count > 0) {
            foreach ($exclude_rows as $row) {
                if ($row['scopename'] == BServiceApp::SERVICETYPESCOPETYPE) {
                    if ($serviceTypeId == $row['service_scope_id'])
                        return FALSE;
                }

                if ($row['scopename'] == BServiceApp::SERVICESCOPETYPE) {
                    if ($serviceId == $row['service_scope_id'])
                        return FALSE;
                }

                if ($row['scopename'] == BServiceApp::SERVICECATEGORYSCOPETYPE) {
                    foreach ($serviceCategoryIds as $serviceCategoryId) {
                        if ($serviceCategoryId == $row['service_scope_id'])
                            return FALSE;
                    }
                }
            }
        }

        //by default, return true
        return TRUE;
    }

    public function getAppRoles($appId) {
        $sql = "select * from bln_application_authitem where app_id = :AppId";

        $db = Yii::app()->getDb();

        $command = $db->createCommand($sql);

        $command->bindParam(":AppId", $appId, PDO::PARAM_INT);

        $dataReader = $command->queryAll();

        $roles = array();

        foreach ($dataReader as $row) {
            array_push($roles, new BAuthItem($row['_id']));
        }

        return $roles;
    }

    public function registerOperations($appId, $operations) {

        $selectSql = "select _id from bln_application_operation where 
            app_id = :AppId and operationname = :OperationName";

        $updateSql = "update bln_application_operation set description = :Description,operationdata = :OperationData 
            where app_id = :AppId and operationName = :OperationName";

        $sql = "insert bln_application_operation(app_id,operationname,description,operationdata) 
            values(:AppId,:OperationName,:Description,:OperationData)";

        $db = Yii::app()->getDb();
        //$command = $db->createCommand($sql);

        $opData = serialize(array());

        foreach ($operations as $key => $operation) {
            $opName = $key;

            if (isset($operation['data']))
                $opData = serialize($operation['data']);

            $selectCommand = $db->createCommand($selectSql);

            $selectCommand->bindParam(":AppId", $appId, pdo::PARAM_INT);
            $selectCommand->bindParam(":OperationName", $opName, pdo::PARAM_STR);

            $opId = $selectCommand->queryScalar();

            if ($opId != NULL) {

                $updateComm = $db->createCommand($updateSql);

                $updateComm->bindParam(":AppId", $appId, pdo::PARAM_INT);
                $updateComm->bindParam(":OperationName", $opName, pdo::PARAM_STR);
                $updateComm->bindParam(":Description", $operation['description'], pdo::PARAM_STR);
                $updateComm->bindParam(":OperationData", $opData, pdo::PARAM_STR);

                $updateComm->execute();
            } else {
                $insertComm = $db->createCommand($sql);
                $insertComm->bindParam(":AppId", $appId, pdo::PARAM_INT);
                $insertComm->bindParam(":OperationName", $opName, pdo::PARAM_STR);
                $insertComm->bindParam(":Description", $operation['description'], pdo::PARAM_STR);
                $insertComm->bindParam(":OperationData", $opData, pdo::PARAM_STR);

                $insertComm->execute();
            }
        }
    }

    public function updateAppData($data) {
        $appId = $this->app->getId();

        $sql = "update bln_application set data = :Data where _id = :AppId";

        $db = Yii::app()->getDb();
        $command = $db->createCommand($sql);

        $s_data = serialize($data);

        $command->bindParam(":Data", $s_data, PDO::PARAM_STR);
        $command->bindParam(":AppId", $appId, PDO::PARAM_INT);

        $command->execute();
    }

    public function getOperationId($appId, $operationName = NULL, $functionName = NULL) {

        if ($functionName != NULL)
            $sql = "select _id from bln_application_operation where app_id = :AppId and functionname=:FunctionName";

        if ($functionName == NULL && $operationName != NULL)
            $sql = "select _id from bln_application_operation where app_id = :AppId and operationname=:OperationName";

        $db = Yii::app()->getDb();
        $command = $db->createCommand($sql);

        $command->bindParam(":AppId", $appId, PDO::PARAM_INT);

        if ($functionName != NULL)
            $command->bindParam(":FunctionName", $functionName, PDO::PARAM_STR);

        if ($functionName == NULL && $operationName != NULL)
            $command->bindParam(":OperationName", $operationName, PDO::PARAM_STR);

        return $command->queryScalar();
    }

    protected function getChildrenRoles($roleId, $idArray = array()) {
        $sql = "select child_id,parent_id from bln_application_authitem_child where parent_id = :ParentId";

        $db = Yii::app()->getDb();
        $command = $db->createCommand($sql);

        $command->bindParam(":ParentId", $roleId, PDO::PARAM_INT);

        $dataReader = $command->execute();

        foreach ($dataReader as $row) {
            $this->getChildrenRoles($row['child_id'], $idArray);
            $idArray[$row['child_id']] = $row['parent_id'];
        }

        return $idArray;
    }

    public function getOperationRequests($operationName, $userData, $serviceData, $serviceAppData, $config = NULL) {

        if ($config == NULL) {
            $status = BOperationRequest::Status_Pending;
            $timeLength = 7 * 24 * 60 * 60;
        } else {
            $status = in_array($config['status'], array(BOperationRequest::Status_Expired, BOperationRequest::Status_Processed)) ?
                    $config['status'] : BOperationRequest::Status_Pending;
            $timeLength = $config['timeLength'];
        }

        $sql = "select * from bln_operation_request 
            where to_user = :UserId and to_service = :ServiceId 
            and to_service_app = :ServiceAppId and status = :Status and start_time + :TimeLength < time()";

        if ($status == BOperationRequest::Status_Pending)
            $sql = "select * from bln_operation_request 
            where (to_user = :UserId or from_user = :UserId) and (to_service = :ServiceId or from_service = :ServiceId) 
            and (to_service_app = :ServiceAppId or from_service_app = :ServiceAppId) and status = :Status and start_time + :TimeLength < time() 
            and start_time + alive_length > time()";

        $sql = "select * from bln_operation_request 
            where (to_user = :UserId) and (to_service = :ServiceId) 
            and (to_service_app = :ServiceAppId) and operationname = :OperationName and status = :Status order by _id desc";

        $db = Yii::app()->getDb();
        $command = $db->createCommand($sql);

        if (isset($userData['userId']))
            $userId = $userData['userId'];

        if (isset($userData['circleId']))
            $userId = BOperationContract::UserType_Circle;

        if (isset($userData['roleId'])) {
            $userId = BOperationContract::UserType_Role;
        }

        $serviceId = $serviceData['serviceId'];
        $serviceAppId = $serviceAppData['serviceAppId'];

        $command->bindParam(":OperationName", $operationName, PDO::PARAM_STR);
        $command->bindParam(":UserId", $userId, PDO::PARAM_INT);
        $command->bindParam(":ServiceId", $serviceId, PDO::PARAM_INT);
        $command->bindParam(":ServiceAppId", $serviceAppId, PDO::PARAM_INT);
        $command->bindParam(":Status", $status, PDO::PARAM_STR);
        //      $command->bindParam(":TimeLength", $timeLength, PDO::PARAM_INT);

        $dataReader = $command->queryAll();

        $retRequests = array();

        foreach ($dataReader as $row) {
            $oReq = new BOperationRequest();
            $oReq->id = $row['_id'];
            $oReq->receiver['userId'] = $row['to_user'];
            $oReq->receiver['serviceId'] = $row['to_service'];
            $oReq->receiver['serviceAppId'] = $row['to_service_app'];
            $oReq->sender['userId'] = $row['from_user'];
            $oReq->sender['serviceId'] = $row['from_service'];
            $oReq->sender['serviceAppId'] = $row['from_service_app'];
            $oReq->operationName = $row['operationname'];
            $oReq->aliveLength = $row['alive_length'];
            $oReq->startTime = $row['start_time'];
            $oReq->data = unserialize($row['operationdata']);
            $oReq->status = $row['status'];

            $retRequests[$row['_id']] = $oReq;
        }

        return $retRequests;
    }

    public function getMessageRequests($opeationName, $userData, $serviceData, $serviceAppData, $config = NULL) {

        if ($config == NULL) {
            $status = BOperationRequest::Status_Pending;
            $timeLength = 7 * 24 * 60 * 60;
        } else {
            $status = in_array($config['status'], array(BOperationRequest::Status_Expired, BOperationRequest::Status_Processed)) ?
                    $config['status'] : BOperationRequest::Status_Pending;
            $timeLength = $config['timeLength'];
        }

        $sql = "select * from bln_message_request 
            where to_user = :UserId and to_service = :ServiceId 
            and to_service_app = :ServiceAppId and status = :Status and start_time + :TimeLength < time()";

        if ($status == BOperationRequest::Status_Pending)
            $sql = "select * from bln_message_request 
            where (to_user = :UserId or from_user = :UserId) and (to_service = :ServiceId or from_service = :ServiceId) 
            and (to_service_app = :ServiceAppId or from_service_app = :ServiceAppId) and status = :Status and start_time + :TimeLength < time() 
            and start_time + alive_length > time()";

        $sql = "select * from bln_message_request 
            where (to_user = :UserId or from_user = :UserId) and (to_service = :ServiceId or from_service = :ServiceId) 
            and (to_service_app = :ServiceAppId or from_service_app = :ServiceAppId) and operationname = :OperationName and status = :Status order by _id desc";

        $db = Yii::app()->getDb();
        $command = $db->createCommand($sql);

        if (isset($userData['userId']))
            $userId = $userData['userId'];

        if (isset($userData['circleId']))
            $userId = BOperationContract::UserType_Circle;

        if (isset($userData['roleId'])) {
            $userId = BOperationContract::UserType_Role;
        }

        $serviceId = $serviceData['serviceId'];
        $serviceAppId = $serviceAppData['serviceAppId'];

        $command->bindParam(":OperationName", $opeationName, PDO::PARAM_STR);
        $command->bindParam(":UserId", $userId, PDO::PARAM_INT);
        $command->bindParam(":ServiceId", $serviceId, PDO::PARAM_INT);
        $command->bindParam(":ServiceAppId", $serviceAppId, PDO::PARAM_INT);
        $command->bindParam(":Status", $status, PDO::PARAM_STR);
        //      $command->bindParam(":TimeLength", $timeLength, PDO::PARAM_INT);

        $dataReader = $command->queryAll();

        $retRequests = array();

        foreach ($dataReader as $row) {
            $oReq = new BOperationRequest();
            $oReq->id = $row['_id'];
            $oReq->receiver['userId'] = $row['to_user'];
            $oReq->receiver['serviceId'] = $row['to_service'];
            $oReq->receiver['serviceAppId'] = $row['to_service_app'];
            $oReq->sender['userId'] = $row['from_user'];
            $oReq->sender['serviceId'] = $row['from_service'];
            $oReq->sender['serviceAppId'] = $row['from_service_app'];
            $oReq->operationName = $row['operationname'];
            $oReq->aliveLength = $row['alive_length'];
            $oReq->startTime = $row['start_time'];
            $oReq->data = unserialize($row['operationdata']);
            $oReq->status = $row['status'];

            if (isset($userData['roleId'])) {
                //$userId = BOperationContract::UserType_Role;
                if ($oReq->data['receiver_roleId'] !== $userData['roleId'])
                    continue;
            }

            $retRequests[$row['_id']] = $oReq;
        }

        return $retRequests;
    }

}

?>
